package com.briup.pai.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.pai.common.constant.DictionaryConstant;
import com.briup.pai.common.enums.ResultCodeEnum;
import com.briup.pai.common.exception.BriupAssert;
import com.briup.pai.convert.DictionaryConvert;
import com.briup.pai.dao.DictionaryMapper;
import com.briup.pai.entity.dto.DictionarySaveDTO;
import com.briup.pai.entity.po.Dictionary;
import com.briup.pai.entity.vo.DictionaryEchoVO;
import com.briup.pai.entity.vo.DictionaryPageVO;
import com.briup.pai.entity.vo.DropDownVO;
import com.briup.pai.entity.vo.PageVO;
import com.briup.pai.service.IDictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@CacheConfig(cacheNames = DictionaryConstant.DICTIONARY_CACHE_PREFIX)
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, Dictionary> implements IDictionaryService {

    @Autowired
    private DictionaryMapper dictionaryMapper;
    @Autowired
    private DictionaryConvert dictionaryConvert;



    @Override
    @CachePut(key = "#result.dictId")
    public DictionaryEchoVO addOrModifyDictionary(DictionarySaveDTO dto) {
        Dictionary dictionary = dictionaryConvert.dictionarySaveDTO2PO(dto);

        //根据dto中是否存在id判断插入还是修改
        if (dictionary.getId() != null) {
            //修改(除了数据校验除外，dictCode不能修改)
            dictionary.setDictCode(null);
            dictionary.setParentId(null);
            dictionaryMapper.updateById(dictionary);

        }else {
            //插入
            //对象转换(将获得的数据转化为字符串po）
            dictionaryMapper.insert(dictionary);

        }

        //插入成功后返回主键
        //对象转换（实体类的po转换为展示用的vo）
       return dictionaryConvert.po2DictionaryEchoVO(dictionaryMapper.selectById(dictionary.getId()));

    }

    @Override
    @Cacheable(key = "#dictionaryId")
    public DictionaryEchoVO getDictionaryById(Integer dictionaryId) {
        //数据字典不为空，使用自定义断言
        Dictionary dictionary = BriupAssert.requireNotNull(this, Dictionary::getId, dictionaryId, ResultCodeEnum.DATA_NOT_EXIST);

        return dictionaryConvert.po2DictionaryEchoVO(dictionaryMapper.selectById(dictionaryId));


    }

    @Override
    @CacheEvict(allEntries = true)
    public void removeDictionaryById(Integer dictionaryId) {
        //根据id删除字典
        //删除一级字典时同步删除所有的二级字典
        //删除二级字典后，如果一级字典下没有二级字典，则同步删除一级字典

        //根据dictionaryID查询并做参数校验
        Dictionary dictionary = BriupAssert.requireNotNull(this, Dictionary::getId, dictionaryId, ResultCodeEnum.DATA_NOT_EXIST);

        //获取数据字典的父id
        Integer parentId = dictionary.getParentId();
        //准备条件构造器
        LambdaQueryWrapper<Dictionary> deleteWrapper = new LambdaQueryWrapper<>();
        //判断对象是几级字典
        if(ObjectUtil.equal(parentId, DictionaryConstant.PARENT_DICTIONARY_ID)){
            //一级字典(都是逻辑外键，不存在级联删除)
            //先删除二级字典
            deleteWrapper.eq(Dictionary::getParentId, dictionaryId);
            dictionaryMapper.delete(deleteWrapper);
            //再删除一级字典
            dictionaryMapper.deleteById(dictionaryId);

        }else {
            //二级字典
            //直接删除
            dictionaryMapper.deleteById(dictionaryId);
            //判断一级字典下是否有二级字典
            // 查询父id下的数据个数为0，就删掉
            deleteWrapper.clear();
            deleteWrapper.eq(Dictionary::getParentId, parentId);
            if (ObjectUtil.equal(this.count(deleteWrapper),0L)){
                dictionaryMapper.deleteById(parentId);

            }

        }
    }

    @Override
    public PageVO<DictionaryPageVO> getDictionaryByPage(Long pageNum, Long pageSize) {
        //准备分页对象
        Page< Dictionary> page = new Page<>(pageNum, pageSize);
        //准备结果
        PageVO<DictionaryPageVO> result = new PageVO<>();
        //查询所有的一级字典，带分页
        LambdaQueryWrapper<Dictionary> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dictionary::getParentId, DictionaryConstant.PARENT_DICTIONARY_ID);
        Page<Dictionary> page1 = dictionaryMapper.selectPage(page, lqw);
        result.setTotal(page1.getTotal());
        result.setData(dictionaryConvert.po2DictionaryPageVOList(page1.getRecords()).stream().peek(dictionaryPageVO -> {
            //根据vo的id查询出所有二级字典
            lqw.clear();
            lqw.eq(Dictionary::getParentId, dictionaryPageVO.getDictId());
            //只对一级字典做分页，二级直接查全部
          List<Dictionary> secondList = dictionaryMapper.selectList(lqw);
          //转换为vo对象
            dictionaryPageVO.setChildren(dictionaryConvert.po2DictionaryPageVOList(secondList));
        }).toList());
        //根据结果查所有的二级字典

        return result;
    }

    @Override
    @Cacheable(key = "T(com.briup.pai.common.constant.CommonConstant).DROPDOWN_CACHE_PREFIX+':'+#dictCode", unless = "#result==null")
    public List<DropDownVO> getDropDownList(String dictCode) {
        //数据字典必须存在
        Dictionary dictionary = BriupAssert.requireNotNull(this, Dictionary::getDictCode, dictCode, ResultCodeEnum.PARAM_IS_ERROR);
        //数据字典必须是一级数据字典
        BriupAssert.requireIn(dictionary.getId(), getParentIdList(), ResultCodeEnum.PARAM_IS_ERROR);
        //查询一级字典所有二级字典
        LambdaQueryWrapper<Dictionary> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dictionary::getParentId, dictionary.getId());
        //转换并返回
        return dictionaryConvert.po2DictionaryDropDownVOList(this.list(lqw));

    }

    @Override
    @Cacheable(key = "T(com.briup.pai.common.constant.DictionaryConstant).DICTIONARY_CACHE_PREFIX+':'+#dictionaryId", unless = "#result==''")
    public String getDictionaryValueById(Integer dictionaryId) {
        Dictionary dictionary = this.getById(dictionaryId);
        return ObjectUtil.isNotNull(dictionary) ? dictionary.getDictValue() : "";
    }

    //获取所有的一级数据字典的id
    private List<Integer> getParentIdList(){
        LambdaQueryWrapper<Dictionary> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dictionary::getParentId, DictionaryConstant.PARENT_DICTIONARY_ID);
        return dictionaryMapper.selectList(lqw).stream().map(Dictionary::getId).toList();
    }
}